//
//  HLEBaseRequest.m
//  HLENetwork_Example
//
//  Created by hle1879 on 2020/9/29.
//  Copyright © 2020 13434436448@163.com. All rights reserved.
//

#import "HLEBaseRequest.h"
#import <AFNetworking/AFNetworking.h>
#import "HLEConst.h"
#import "HLEBaseResponse.h"
#import "HLESessionManager.h"
#import "HLENetWorkCache.h"
#import "NSDictionary+HLENetWork.h"
#import "NSArray+HLENetWork.h"

@interface HLEBaseRequest ()

@property (nonatomic,strong) NSURLSessionDataTask *task;

@end

@implementation HLEBaseRequest

-(instancetype)init{
    self = [super init];
    if (self) {
        self.enableLog = NO;
        self.method = HLERequestMethodGET;
        self.cachePolicy = HLECachePolicyRequestWithoutCahce;
        self.cacheValidTime = CacheValidTimeWeek;
    }
    return self;
}

- (NSURLSessionDataTask*)getTask{
    return self.task;
}

- (void)sendRequest{
    [self addDelegateForDataTask];
    [self logRequestInfo];
    if (self.cachePolicy == HLECachePolicyMainCacheSaveRequest){
        __weak typeof(self) weakSelf = self;
        [HLENetWorkCache getCacheWithRequest:self validTime:self.cacheValidTime completion:^(NSString * _Nonnull key, id<NSCoding> _Nullable cacheData) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (cacheData) {
                [strongSelf logResponseInfo:(HLEBaseResponse*)cacheData isCache:YES];
                strongSelf.cacheCompletion ? strongSelf.cacheCompletion((HLEBaseResponse*)cacheData) : nil;
                [strongSelf removeDelegateForDataTask];
            }
            [strongSelf dealNoCacheRequest:^(HLEBaseResponse * _Nullable response) {
                if (response.success) {
                    [HLENetWorkCache setCacheWithRequest:strongSelf cacheData:response validTime:strongSelf.cacheValidTime completion:^{
                    }];
                }
                if (!cacheData) {
                    [strongSelf logResponseInfo:response isCache:NO];
                    strongSelf.responseCompletion ? strongSelf.responseCompletion(response) : nil;
                    [strongSelf removeDelegateForDataTask];
                }
            }];
        }];
    }else if (self.cachePolicy == HLECachePolicyOnlyCacheOnceRequest){
        __weak typeof(self) weakSelf = self;
        [HLENetWorkCache getCacheWithRequest:self validTime:self.cacheValidTime completion:^(NSString * _Nonnull key, id<NSCoding> _Nullable cacheData) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (!cacheData) {
                [strongSelf logResponseInfo:(HLEBaseResponse*)cacheData isCache:YES];
                strongSelf.cacheCompletion ? strongSelf.cacheCompletion((HLEBaseResponse*)cacheData) : nil;
                [strongSelf removeDelegateForDataTask];
            }else{
                [strongSelf dealNoCacheRequest:^(HLEBaseResponse * _Nullable response) {
                    if (response.success) {
                        [HLENetWorkCache setCacheWithRequest:strongSelf cacheData:response validTime:strongSelf.cacheValidTime completion:^{
                        }];
                    }
                    [strongSelf logResponseInfo:response isCache:NO];
                    strongSelf.responseCompletion ? strongSelf.responseCompletion(response) : nil;
                    [strongSelf removeDelegateForDataTask];
                }];
            }
        }];
    }else if (self.cachePolicy == HLECachePolicyMainRequestFailCache){
        __weak typeof(self) weakSelf = self;
        [self dealNoCacheRequest:^(HLEBaseResponse * _Nullable response) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (response.success) {
                [HLENetWorkCache setCacheWithRequest:strongSelf cacheData:response validTime:strongSelf.cacheValidTime completion:^{
                }];
                [strongSelf logResponseInfo:response isCache:NO];
                strongSelf.responseCompletion ? strongSelf.responseCompletion(response) : nil;
                [strongSelf removeDelegateForDataTask];
            }else{
                [HLENetWorkCache getCacheWithRequest:strongSelf validTime:strongSelf.cacheValidTime completion:^(NSString * _Nonnull key,  id<NSCoding> _Nullable cacheData) {
                    [strongSelf logResponseInfo:(HLEBaseResponse*)cacheData isCache:YES];
                    strongSelf.cacheCompletion ? strongSelf.cacheCompletion((HLEBaseResponse*)cacheData) : nil;
                    [strongSelf removeDelegateForDataTask];
                }];
            }
        }];
    }else if(self.cachePolicy == HLECachePolicyRequsetAndCache){
        __weak typeof(self) weakSelf = self;
        [HLENetWorkCache getCacheWithRequest:self validTime:self.cacheValidTime completion:^(NSString * _Nonnull key,  id<NSCoding> _Nullable cacheData) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (!cacheData) {
                strongSelf.cacheCompletion ? strongSelf.cacheCompletion((HLEBaseResponse*)cacheData) : nil;
            }
        }];
        [self dealNoCacheRequest:^(HLEBaseResponse * _Nullable response) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (response.success) {
                [HLENetWorkCache setCacheWithRequest:strongSelf cacheData:response validTime:strongSelf.cacheValidTime completion:^{
                }];
            }
            [strongSelf logResponseInfo:response isCache:NO];
            strongSelf.responseCompletion ? strongSelf.responseCompletion(response) : nil;
            [strongSelf removeDelegateForDataTask];
        }];
    }else{
        __weak typeof(self) weakSelf = self;
        [self dealNoCacheRequest:^(HLEBaseResponse * _Nullable response) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            [strongSelf logResponseInfo:response isCache:NO];
            strongSelf.responseCompletion ? strongSelf.responseCompletion(response) : nil;
            [strongSelf removeDelegateForDataTask];
        }];
    }
}

- (void)dealNoCacheRequest:(void (^)(HLEBaseResponse* _Nullable))completion{
    if (!self.url) {
        self.url = @"";
    }
    NSError *error = nil;
    NSMutableURLRequest *request = [self.session.sessionManager.requestSerializer requestWithMethod:[self requestTypeWithMethod] URLString:[[NSURL URLWithString:self.url relativeToURL:self.session.config.baseURL] absoluteString] parameters:[self disposePublicParameters] error:&error];
    if (error) {
        HLEBaseResponse *result = [[HLEBaseResponse alloc]initWithResponse:nil responseObject:nil error:error];
        completion ? completion(result) : nil;
        [self logResponseInfo:result isCache:NO];
        return;
    }
    [self disposeRequestMutableHeaderField:request];
    self.task = [self.session.sessionManager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
    } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        HLEBaseResponse *result = [[HLEBaseResponse alloc]initWithResponse:response responseObject:responseObject error:error];
        completion ? completion(result) : nil;
    }];
    [self.task resume];
}


- (void)cancelRequest{
    if (!self.task) {
        [self.task cancel];
    }
    [self removeDelegateForDataTask];
}

- (NSString *)requestTypeWithMethod {
    NSString *requestMethod = @"GET";
    switch (self.method) {
        case HLERequestMethodGET:
            requestMethod = @"GET";
            break;
        case HLERequestMethodPOST:
            requestMethod = @"POST";
            break;
        case HLERequestMethodHEAD:
            requestMethod = @"HEAD";
            break;
        case HLERequestMethodPUT:
            requestMethod = @"PUT";
            break;
        case HLERequestMethodPATCH:
            requestMethod = @"PATCH";
            break;
        case HLERequestMethodDELETE:
            requestMethod = @"DELETE";
            break;
            
        default:
            break;
    }
    return requestMethod;
}

- (NSDictionary *)disposePublicParameters{
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:self.params];
    if (self.session.config.publicParams && self.session.config.publicParams.count > 0) {
        [params addEntriesFromDictionary:self.session.config.publicParams];
    }
    return params.copy;
}

- (void)disposeRequestMutableHeaderField:(NSMutableURLRequest *)request {
    if (self.session.config.requestHeader && self.session.config.requestHeader.count > 0) {
        for (NSString *key in self.session.config.requestHeader) {
            id value = self.session.config.requestHeader[key];
            [request setValue:value forHTTPHeaderField:key];
        }
    }
    for (NSString *key in self.requestHeader) {
        id value = self.requestHeader[key];
        [request setValue:value forHTTPHeaderField:key];
    }
}

- (void)addDelegateForDataTask{
    if (![self.session.allRequests containsObject:self]) {
        [self.session.allRequests addObject:self];
    }
}

- (void)removeDelegateForDataTask{
    if ([self.session.allRequests containsObject:self]) {
        [self.session.allRequests removeObject:self];
    }
}


-(HLESessionManager *)session{
    if (!_session) {
        _session = [HLESessionManager defaultManager];
    }
    return _session;
}

- (void)logRequestInfo{
#ifdef DEBUG
    if (self.enableLog) {
        NSMutableDictionary *requestHeader = [NSMutableDictionary dictionaryWithDictionary:self.requestHeader];
        if (self.session.config.requestHeader && self.session.config.requestHeader.count > 0) {
            [requestHeader addEntriesFromDictionary:self.session.config.requestHeader];
        }
        NSLog(@"\n==================发送请求==================\n\
              \n===请求地址:%@\n\
              \n===请求方式:%@\n\
              \n===请求参数:%@\n\
              \n===请求头:%@\n\
              \n===========================================",
              self.url,
              [self requestTypeWithMethod],
              [self disposePublicParameters],
              requestHeader);
    }
#endif
}

- (void)logResponseInfo:(HLEBaseResponse*)response isCache:(BOOL)isCache{
#ifdef DEBUG
    if (self.enableLog) {
        NSLog(@"\n==================请求结束==================\n\
              \n===请求地址:%@\n\
              \n===是否是缓存:%@\n\
              \n===%@\n\
              \n===========================================",
              self.url,
              (isCache ? @"YES" : @"NO"),
              (response.success ?
               [NSString stringWithFormat:@"===成功请求返回:%@",response.responseObject] :
               [NSString stringWithFormat:@"===失败请求返回:%@",response.error])
              );
    }
#endif
}

- (void)dealloc{
    NSLog(@"%@=====dealloc",self);
}
@end
